import {
    CommandInvoker,
    CommandListener,
    CommandOptions,
    CommandResult,
    DataHandlerFunc
} from './command'
import {StringDecoder} from 'string_decoder'

export async function call(
    command: string,
    args?: string[],
    workPath?: string,
    options?: CommandOptions
): Promise<number> {
    const invoker: CommandInvoker = new CommandInvoker(command, args, workPath, options)
    return await invoker.callCommand()
}

export async function callOutput(
    command: string,
    args?: string[],
    workPath?: string,
    options?: CommandOptions
): Promise<CommandResult> {
    let stdoutContent = ''
    let stderrContent = ''

    const stdoutDecoder = new StringDecoder('utf8')
    const stderrDecoder = new StringDecoder('utf8')

    const originalStdoutListener: DataHandlerFunc | undefined =
        options?.listener?.stdout
    const originalStdErrListener: DataHandlerFunc | undefined =
        options?.listener?.stderr

    const stdErrListener: DataHandlerFunc = (data: Buffer): void => {
        stderrContent += stderrDecoder.write(data)
        if (originalStdErrListener) {
            originalStdErrListener(data)
        }
    }

    const stdOutListener: DataHandlerFunc = (data: Buffer): void => {
        stdoutContent += stdoutDecoder.write(data)
        if (originalStdoutListener) {
            originalStdoutListener(data)
        }
    }

    const listener: CommandListener = {
        ...options?.listener,
        stdout: stdOutListener,
        stderr: stdErrListener
    }

    const exitCode = await call(command, args, workPath, {...options, listener})

    stdoutContent += stdoutDecoder.end()
    stderrContent += stderrDecoder.end()

    return {exitCode, stdoutContent, stderrContent}
}
